package tt.dz.egobus.servicemanager.service.impl;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tt.dz.egobus.api.ResponseBack;
import tt.dz.egobus.api.apushservice.PushVo;
import tt.dz.egobus.api.exception.ResponseException;
import tt.dz.egobus.api.managerservice.manager.*;
import tt.dz.egobus.api.usercenter.user.UserInfoBack;
import tt.dz.egobus.bean.BusinessStatus;
import tt.dz.egobus.bean.I18NCode;
import tt.dz.egobus.bean.Pagination;
import tt.dz.egobus.bean.ServiceManagerI18NCodeEnum;
import tt.dz.egobus.emuns.OrderSn;
import tt.dz.egobus.servicemanager.business.constant.BusinessTypeEnum;
import tt.dz.egobus.servicemanager.business.convert.BespeakTimeRedisRestoreConvertor;
import tt.dz.egobus.servicemanager.business.convert.BusinessIdRedisTopicMessageConverter;
import tt.dz.egobus.servicemanager.business.convert.FilterBusInnerPointConverter;
import tt.dz.egobus.servicemanager.business.convert.ServiceByRequestType;
import tt.dz.egobus.servicemanager.business.distribute.BespeakSystemDistributeBusinessContext;
import tt.dz.egobus.servicemanager.business.distribute.RightNowSystemDistributeBusinessContext;
import tt.dz.egobus.servicemanager.business.distribute.SystemDistributeBusinessContext;
import tt.dz.egobus.servicemanager.business.grab.BespeakGrabBusiness;
import tt.dz.egobus.servicemanager.business.grab.GrabBusinessContext;
import tt.dz.egobus.servicemanager.business.grab.RightNowGrabBusiness;
import tt.dz.egobus.servicemanager.business.key.BusinessCache;
import tt.dz.egobus.servicemanager.business.key.DriverStatus;
import tt.dz.egobus.servicemanager.business.listener.RedisEventPublish;
import tt.dz.egobus.servicemanager.business.listener.handler.BusinessIdExpireRedisEventPublish;
import tt.dz.egobus.servicemanager.business.lock.BusinessLock;
import tt.dz.egobus.servicemanager.business.lock.BusinessRedisLock;
import tt.dz.egobus.servicemanager.business.point.AddressPoint;
import tt.dz.egobus.servicemanager.business.point.BusPoint;
import tt.dz.egobus.servicemanager.business.task.PushTaskRunnable;
import tt.dz.egobus.servicemanager.business.task.job.DriverGrabBusinessTimeout;
import tt.dz.egobus.servicemanager.business.task.job.UserRequestBusinessTimeout;
import tt.dz.egobus.servicemanager.core.task.DynamicTaskManager;
import tt.dz.egobus.servicemanager.core.task.DynamicTaskNamespace;
import tt.dz.egobus.servicemanager.entities.Bus;
import tt.dz.egobus.servicemanager.entities.BusinessService;
import tt.dz.egobus.servicemanager.entities.BusinessServiceInfo;
import tt.dz.egobus.servicemanager.entities.DriverRegisterBusRelative;
import tt.dz.egobus.servicemanager.facade.driver.DriverFacade;
import tt.dz.egobus.servicemanager.facade.terminal.TerminalFacade;
import tt.dz.egobus.servicemanager.service.*;
import tt.dz.egobus.servicemanager.util.PojoConvertVoUtils;
import tt.dz.egobus.servicemanager.vo.BusinessFinishVo;
import tt.dz.egobus.servicemanager.vo.BusinessRequestVo;
import tt.dz.egobus.vo.KV;

import javax.validation.ConstraintViolationException;
import java.util.*;
import java.util.concurrent.ThreadPoolExecutor;

import static tt.dz.egobus.bean.I18NCodeEnum.*;
import static tt.dz.egobus.bean.ServiceManagerI18NCodeEnum.*;

/**
 * @author Anson
 * @date 17-8-9
 * @name 抢单业务的管理服务实现类
 * @since 1.0.6
 */
@Service("grabManagerServiceImpl")
public class GrabManagerServiceImpl extends ManagerServiceImpl implements GrabManagerService {


    private final static BusinessIdRedisTopicMessageConverter BUSINESS_ID_CONVERTER = new BusinessIdRedisTopicMessageConverter();

    @Autowired
    @Qualifier("grabRedisBusinessWorkCacheServiceImpl")
    GrabRedisBusinessWorkCacheService grabBusinessWorkCacheService;

    @Autowired
    @Qualifier("grabRedisBusinessCacheServiceImpl")
    GrabBusinessCacheService grabBusinessCacheService;

    @Autowired
    @Qualifier("springQuartzTaskManagerImpl")
    DynamicTaskManager dynamicTaskManager;

    @Autowired
    @Qualifier("redisDynamicTaskMapService")
    DynamicTaskService dynamicTaskService;

    @Autowired
    @Qualifier("standardThreadExecutor")
    ThreadPoolExecutor executor;

    @Autowired
    @Qualifier("grabDriverRegisterBusRelativeServiceImpl")
    GrabDriverRegisterBusRelativeService grabDriverRegisterBusRelativeService;

    @Autowired
    ApplicationContext applicationContext;

    @Autowired
    @Qualifier("redisTemplate")
    RedisTemplate redisTemplate;

    @Autowired
    @Qualifier("businessIdExpireRedisEventPublish")
    RedisEventPublish redisEventPublish;

    private final BespeakTimeRedisRestoreConvertor convertor = new BespeakTimeRedisRestoreConvertor();

    @Override
    @Transactional
    public ResponseBack<Boolean> active(String busId, String driverId) {
        try {
            RedisBusinessWorkCacheServiceImpl.RedisCacheLock driverLock = new RedisBusinessWorkCacheServiceImpl.RedisCacheLock(this.extendCacheService, driverId);
            try {
                boolean isActive = false;
                if (driverLock.aquireLock()) {
                    //不存在有效的车服务，即车没有注册有效的服务
                    int[] businessCodes = this.busRegisterServiceService.queryBusinessCodeByBusId(busId);
                    if (ArrayUtils.isEmpty(businessCodes)) {
                        throw new ResponseException(RPC_BUS_UN_BIND_SERVICE_ERROR);
                    }
                    DriverStatus status = grabBusinessWorkCacheService.getStatus(driverId);
                    LOGGER.info("抢单模式,司机上线触发->当前获取司机状态={}", status);
                    //$$校验当前司机端的状态是否一致
                    if (status != null && !DriverRegisterBusRelative.RelativeStatus.assertUnActive(status.getStatus())) {
                        throw new ResponseException(RPC_DRIVER_CAN_NOT_ACTIVE_ERROR);
                    }
                    UserInfoBack driverInfo = validateAndGetUserInfo(driverId);
                    Bus bus = validateBus(busId);
                    if (!bus.assertNotUsed()) {
                        //当前车的类型没有处于未使用的状态
                        throw new ResponseException(RPC_BUS_CAN_NOT_ACTIVE_ERROR);
                    }
                    //车是否存在绑定关系
                    boolean isBindedCar = driverRegisterBusRelativeService.isValidateBindCar(busId);
                    //司机是否已经存在绑定关系
                    boolean isBindedDriverCar = driverRegisterBusRelativeService.isValidateBindDriver(driverId);
                    //检查当前是否存在已经绑定的关系
                    if (isBindedCar || isBindedDriverCar) {
                        //进入当前条件下,只有两种:车已经被用了,司机已经被绑定了关系
                        ServiceManagerI18NCodeEnum i18NCodeEnum = isBindedCar ? RPC_BUS_CAN_NOT_ACTIVE_ERROR :
                                RPC_DRIVER_CAN_NOT_ACTIVE_ERROR;
                        throw new ResponseException(i18NCodeEnum);
                    }
                    //bus的状态在数据库要同步为在使用中
                    isActive = this.driverRegisterBusRelativeService.active(busId, driverInfo);
                    if (isActive) {
                        grabBusinessWorkCacheService.active(driverId, businessCodes);
                    }
                }
                return ResponseBack.success(isActive);
            } finally {
                driverLock.unlock();
            }
        } catch (ResponseException e) {
            return ResponseBack.error(e);
        }
    }

    @Override
    @Transactional
    public ResponseBack<Boolean> driverGrabAcceptAndBeginTask(String driverId, String businessId) {
        if (StringUtils.isAnyEmpty(driverId, businessId)) {
            throw new ResponseException(RPC_PARAM_ILLEGAL_ERROR);
        }
        BusinessCache businessCache = this.grabBusinessCacheService.get(businessId);
        ResponseBack<Boolean> isAcceptSuccess = this.businessDoBeginHandle(driverId, businessId, BusinessTypeEnum
                .GRAB_LEAFLETS);
        if (isAcceptSuccess.isSuccess() && isAcceptSuccess.getResult()) {
            //当前抢单任务完成了之后,则需要进行取消当前动态任务
            this.terminalDynamicTask(businessId);
            //当前司机抢单成功了之后,则处理其他司机的状态
            this.terminalBusinessDriverStatus(businessCache, driverId);
        }

        return isAcceptSuccess;
    }

    /**
     * @param businessCache   当前业务状态
     * @param excludeDriverId 不处理的司机状态
     * @author Anson
     * @date 17-9-8
     * @name 处理业务抢单结束的时候, 司机其他司机状态
     * @since 1.0.7
     */
    @Transactional
    protected void terminalBusinessDriverStatus(BusinessCache businessCache, String excludeDriverId) {
        if (businessCache == null) {
            return;
        }
        BusPoint[] busPoints = businessCache.getDrivers();
        if (busPoints == null || busPoints.length == 0) {
            return;
        }
        String businessId = businessCache.getBusinessId();
        if (StringUtils.isBlank(businessId)) {
            return;
        }
        excludeDriverId = StringUtils.defaultString(excludeDriverId, "");
        List<String> needHandlerDriverDbStatusActive = new ArrayList<>();
        int driverStatus = -1;
        String curDriverId = "";
        String curBusinessId = "";
        DriverStatus curDriverStatus = null;
        for (BusPoint busPoint : busPoints) {
            curDriverId = busPoint.getDriverId();
            if (excludeDriverId.equals(curDriverId)) {
                continue;
            }
            curDriverStatus = this.businessWorkCacheService.getStatus(curDriverId);
            if (curDriverStatus == null) {
                continue;
            }
            curBusinessId = curDriverStatus.getBusinessId();
            if (StringUtils.isBlank(curBusinessId) || !curBusinessId.equals(businessId)) {
                //确信当前司机的业务是本次业务
                continue;
            }
            if (DriverRegisterBusRelative.RelativeStatus.assertGrabBusiness(curDriverStatus.getStatus())) {
                //确认当前司机状态处于抢单状态的时候,转变的当前业务为开始状态,并且清楚当前businessId关系
                needHandlerDriverDbStatusActive.add(curDriverId);
                this.grabBusinessWorkCacheService.doGrabFail(curDriverId);
            }
            if (DriverRegisterBusRelative.RelativeStatus.assertActive(curDriverStatus.getStatus())) {
                //当前司机放弃了当前单,则需要抢单失败,设置当前bussiness为空
                this.grabBusinessWorkCacheService.doGrabFail(curDriverId);
            }
        }
        if (!CollectionUtils.isEmpty(needHandlerDriverDbStatusActive)) {
            //批量处理当前司机在数据库中的状态
            int originalSize = needHandlerDriverDbStatusActive.size();
            int updateSize = this.grabDriverRegisterBusRelativeService.terminalBusinessDriverStatus(needHandlerDriverDbStatusActive);
            LOGGER.info("处理业务抢单结束的时候, 司机其他司机状态,批量处理当前司机在数据库中的状态,originalSize={},updateSize={}", originalSize, updateSize);
        }
    }

    /**
     * @param
     * @author Anson
     * @date 17-8-9
     * @name 基于抢单模式的抢单
     * @since 1.0.6
     */
    @Override
    @Transactional
    public ResponseBack<Boolean> doGrabBusiness(String driverId, String businessId, String userId, BusPoint busPoint,
                                                BusinessRequestVo businessRequestVo) {
        KV<Integer, DriverRegisterBusRelative> relativeKV = null;
        boolean isDone = false;
        DriverRegisterBusRelative relative = null;
        try {
            LOGGER.info("driverId={},抢到当前业务锁,businessId={}", driverId, businessId);
            relativeKV = this.getValidateDriverRegisterBusRelative(driverId, this.driverRegisterBusRelativeService);
            relative = relativeKV.getV();
            if (!relative.isAbleDoBeginBusinessInGrab()) {
                LOGGER.info("基于抢单模式的抢单->当前不是可以接单的状态,driverId={},businessId={}", driverId, businessId);
                return ResponseBack.success(false);
            }
            //当前状态必须处于抢单中,否则都可以认为是抢单结束了
            ResponseBack<Boolean> isGrabLive = this.businessGrabIsLive(businessId);
            if ((!isGrabLive.isSuccess()) && (!isGrabLive.getResult())) {
                //当前抢单流程已经不存在的时候,抢单失败
                LOGGER.info("基于抢单模式的抢单->当前抢单流程已经不存在的时候,抢单失败,driverId={},businessId={}",
                        driverId, businessId);
                return ResponseBack.success(isDone);
            }
            //确信当前司机绑定的业务为当前业务
            DriverStatus driverStatus = this.grabBusinessWorkCacheService.getStatus(driverId);
            if (driverStatus == null || !StringUtils.defaultString(driverStatus.getBusinessId(), "").trim()
                    .equals(businessId)) {
                LOGGER.info("基于抢单模式的抢单->当前司机绑定的业务不是当前业务,抢单失败,driverId={},businessId={}",
                        driverId, businessId);
                return ResponseBack.success(false);
            }
            //若存在当前业务的时候
            BusinessService businessService = this.businessServiceService.getBusinessByBusinessId(businessId);
            if (businessService != null) {
                LOGGER.info("基于抢单模式的抢单->已经存在当前数据库的业务,driverId={},businessId={}",
                        driverId, businessId);
                return ResponseBack.success(false);
            }
            UserRequestTypeInfo.UserRequestType type = UserRequestTypeInfo.UserRequestType.indexOf
                    (businessRequestVo.getUserRequestInfo().getType());
            GrabBusinessContext grabBusinessContext = null;
            switch (type) {
                case BESPEAK:
                    grabBusinessContext = new BespeakGrabBusiness(relative, busPoint);
                    break;
                case NOW:
                    grabBusinessContext = new RightNowGrabBusiness(relative, busPoint);
                    break;
            }
            if (grabBusinessContext == null) {
                LOGGER.info("基于抢单模式的抢单->GrabBusinessContext为空,driverId={},businessId={}",
                        driverId, businessId);
                isDone = false;
            } else {
                grabBusinessContext.setApplicationContext(applicationContext);
                isDone = grabBusinessContext.handleGrabBusiness(businessRequestVo, businessId, driverId);
            }

        } catch (ConstraintViolationException e) {
            //c=出现相关异常的时候,回退到激活的状态
            isDone = false;
            LOGGER.error("当前获取司机并未能抢单当前业务流程的锁,线程阻塞,driverId={}", driverId);
            return ResponseBack.success(false);
        } finally {
            LOGGER.info("driverId={},释放当前业务锁,businessId={}", driverId, businessId);
            if (!isDone) {
                grabBusinessWorkCacheService.doGrabFail(driverId);
                if (relative != null) {
                    grabDriverRegisterBusRelativeService.giveUpDriverBusinessGrab(relative);
                }
            }
        }
        return ResponseBack.success(isDone);
    }


    @Override
    @Transactional
    public ResponseBack<Boolean> businessGrabIsLive(String businessId) {
        BusinessCache businessCache = businessCacheService.get(businessId);
        if (businessCache == null) {
            //当前业务缓存已经被删除
            return ResponseBack.success(false);
        }
        Integer status = businessCache.getStatus();
        boolean isGrab = BusinessStatus.assertGrabBusiness(status);
        return ResponseBack.success(isGrab);
    }

    @Override
    @Transactional
    public ResponseBack<Boolean> businessGrabTimeout(String businessId) {
        BusinessCache businessCache = businessCacheService.get(businessId);
        if (businessCache == null) {
            //当前业务缓存已经被删除,则表明抢单结束了
            return ResponseBack.success(true);
        }
        Integer status = businessCache.getStatus();
        boolean isGrab = BusinessStatus.assertGrabBusinessTimeout(status);
        return ResponseBack.success(isGrab);
    }

    @Override
    @Transactional
    public ResponseBack<Boolean> businessGrabFinish(String businessId) {
        BusinessCache businessCache = businessCacheService.get(businessId);
        if (businessCache == null) {
            //当前业务缓存已经被删除,则表明抢单结束了
            return ResponseBack.success(true);
        }
        Integer status = businessCache.getStatus();
        boolean isGrab = BusinessStatus.assertGrabFinish(status);
        return ResponseBack.success(isGrab);
    }

    @Override
    @Transactional
    public ResponseBack<Boolean> doGrabLost(String businessId) {

        BusinessLock lock = new BusinessRedisLock(this.extendCacheService);
        lock.setBusinessId(businessId);
        boolean isGrab = false;
        try {
            if (lock.aquireLock()) {
                //如果当前业务状态已经处于结束的状态的时候
                ResponseBack<Boolean> isFinish = this.businessGrabFinish(businessId);
                if (isFinish.isSuccess() && isFinish.getResult()) {
                    return isFinish;
                }
                LOGGER.info("当前用户请求的任务已经完成,不满足用户请求超时,businessId={}", businessId);
                isGrab = this.grabBusinessCacheService.doGrabLost(businessId);
                LOGGER.info("当前用户请求的任务已经完成,处于业务流单业务逻辑,businessId={},isGrab={}", businessId, isGrab);
            }
        } finally {
            lock.unlock();
        }


        return ResponseBack.success(isGrab);
    }

    @Override
    @Transactional
    public ResponseBack<Boolean> doGrabTimeout(String businessId) {
        boolean isDone = false;
        ResponseBack<Boolean> isHandlerDistributeSuccess = ResponseBack.success(isDone);
        BusinessLock lock = new BusinessRedisLock(this.extendCacheService);
        lock.setBusinessId(businessId);
        try {
            if (lock.aquireLock()) {
                //确保当前的状态处于抢单中
                ResponseBack<Boolean> isInGrab = this.businessGrabIsLive(businessId);
                if (!(isInGrab.isSuccess() && isInGrab.getResult())) {
                    //当前状态不处于抢单状态的时候
                    LOGGER.info("当前业务状态不处于抢单中,不执行抢单超时businessId={}", businessId);
                    return isInGrab;
                }
                isDone = this.grabBusinessCacheService.doGrabTimeout(businessId);
                LOGGER.info("抢单超时业务处理,抢单超时处理businessId={},isDone={}", businessId, isDone);
                if (!isDone) {
                    //设置当前业务缓存状态为抢单超时的不成功
                    return ResponseBack.success(false);
                }
                //下一步就采用了系统派单的的服务接口
                BusinessCache businessCache = this.grabBusinessCacheService.get(businessId);
                if (businessCache == null) {
                    throw new ResponseException(RPC_PARAM_ILLEGAL_ERROR);
                }
                //过滤出非内部人员
                FilterBusInnerPointConverter converter = new FilterBusInnerPointConverter();
                BusPoint[] points = converter.convert(businessCache);
                if (ArrayUtils.isEmpty(points)) {
                    //当前不存在内部司机派单的不成功
                    return ResponseBack.success(false);
                }
                boolean isDistributSuccess = false;
                LOGGER.info("抢单超时处理,开始系统派单,并且转变当前司机状态为(激活|业务)状态businessId={},points.length={}", businessId, points
                        .length);
                for (BusPoint busPoint : points) {
                    if (!isDistributSuccess) {
                        isHandlerDistributeSuccess = this.businessDoBeginHandle(busPoint.getDriverId(), businessId,
                                BusinessTypeEnum.DISTRIBUTE_LEAFLETS);
                        if (isDistributSuccess = (isHandlerDistributeSuccess.isSuccess() &&
                                isHandlerDistributeSuccess.getResult())) {
                            LOGGER.info("抢单超时处理,开始系统派单成功,异步推单businessId={},driverId={}", businessId, busPoint
                                    .getDriverId());

                        } else {
                            //当前司机派单不成功的时候
                            this.driverGiveUpGrabTask(busPoint.getDriverId(), businessId);
                        }
                    } else {
                        //派单已经成功了,其他司机放弃抢单
                        this.driverGiveUpGrabTask(busPoint.getDriverId(), businessId);
                    }
                }
            }
        } finally {
            lock.unlock();
        }

        return isHandlerDistributeSuccess;
    }

    /**
     * @param businessId
     * @author Anson
     * @date 17-9-9
     * @name 推单给用户端, 有有用户端进行司机分发推单
     * @since 1.0.7
     */
    @Override
    public void pushBusinessHandler(String businessId) {
        DriverFacade driverFacade = this.getFacadeFactory().getBean("driver", DriverFacade.class);
        PushVo pushVo = new PushVo();
        pushVo.setBusinessId(businessId);
        pushVo.setBusinessType(PushVo.MessageType.USER_ORDER_PUSH.value());
        PushTaskRunnable.PushTask pushTask = new PushTaskRunnable.PushTask(pushVo, 2);
        executor.execute(new PushTaskRunnable(driverFacade, pushTask));
    }


    /**
     * @param userId     用户id
     * @param businessId 业务id
     * @return 返回当前抢单的数据
     * @author Anson
     * @date 17-8-7
     * @name 用户取消抢单流程
     * @desc 用户在未接收到真正订单时候, 可取消当前抢单流程
     * @since 1.0.6
     */
    @Override
    @Transactional
    public ResponseBack<DistributeDriverTask> userCancelGrabBusiness(String userId, String businessId) {
        if (StringUtils.isEmpty(userId) || StringUtils.isEmpty(businessId)) {
            throw new ResponseException(RPC_PARAM_ILLEGAL_ERROR);
        }
        BusinessCache businessCache = this.grabBusinessCacheService.get(businessId);
        if (businessCache == null) {
            throw new ResponseException(RPC_PARAM_ILLEGAL_ERROR);
        }
        int status = businessCache.getStatus();
        if (!BusinessStatus.assertGrabBusiness(status)) {
            I18NCode errorCode = null;
            if (BusinessStatus.assertBeginBusiness(status)) {
                //司机接到单子,可提示用户进行取消行程流程
                errorCode = RPC_USER_CANCEL_GRAB_ON_GRAB_OVER;
            } else if (BusinessStatus.assertBusiness(status)) {
                //开始了行程,用户取消失败,行程已经开始
                errorCode = RPC_USER_CANCEL_GRAB_ON_IN_BUSINESS;
            } else if (BusinessStatus.assertLossBusinessTimeout(status)) {
                //系统已经流单了,则时候返回用户取消失败,系统超时已经取消本次请求
                errorCode = RPC_USER_CANCEL_ON_BUSINESS_LOST;
            } else {
                errorCode = RPC_USER_CANCEL_ERROR;
            }
            LOGGER.error("当前用户取消请求叫车失败,errorCode={},businessId={}", errorCode, businessId);
            throw new ResponseException(errorCode);
        }
        LOGGER.info("当前用户取消请求叫车,businessId={}", businessId);
        BusinessLock lock = new BusinessRedisLock(this.extendCacheService);
        lock.setBusinessId(businessId);
        DistributeDriverTask distributeDriverTask = null;
        try {
            if (lock.aquireLock()) {
                this.grabBusinessCacheService.updateStatus(businessId, BusinessStatus.TERMINATION_BUSINESS);
                //业务缓存转换当前的分发信息
                distributeDriverTask = PojoConvertVoUtils.businessCacheConvertDistributeDriverTask(businessCache);
                BusPoint[] busPoints = businessCache.getDrivers();
                if (!ArrayUtils.isEmpty(busPoints)) {
                    //如果当前用户取消了,则将当前司机的状态转换为激活状态
                    for (BusPoint busPoint : busPoints) {
                        this.driverGiveUpGrabTask(busPoint.getDriverId(), businessId);
                    }
                }
                //删除当前动态定时任务
                this.terminalDynamicTask(businessId);
                this.grabBusinessCacheService.deleteBusiness(businessId);
            } else {
                throw new ResponseException(RPC_USER_CANCEL_ERROR);
            }
        } finally {
            lock.unlock();
        }

        return ResponseBack.success(distributeDriverTask);
    }

    @Override
    @Transactional
    public ResponseBack<Boolean> terminalDynamicTask(String businessId) {
        ResponseBack<Boolean> isFinishGrab = this.businessGrabFinish(businessId);
        //当前派单成功了之后,则需要进行取消当前任务
        if (isFinishGrab.isSuccess() && isFinishGrab.getResult()) {
            LOGGER.info("当前抢单流程已经结束,则需要删除相关动态任务,businessId={}", businessId);
            BusinessCache cache = this.grabBusinessCacheService.get(businessId);
            if (cache == null) {
                return ResponseBack.success(false);
            }
            DynamicTaskNamespace userRequestTimeoutNamespace = DynamicTaskNamespace
                    .dynamicTaskNamespaceByBusinessCache(cache, UserRequestBusinessTimeout.class);
            if (userRequestTimeoutNamespace != null) {
                LOGGER.info("当前抢单流程已经结束,则需要进行取消当前用户超时的任务,businessId={}", businessId);
                dynamicTaskManager.removeJob(userRequestTimeoutNamespace);
                dynamicTaskService.deleteDynamicTaskNamespace(userRequestTimeoutNamespace);
            }

            DynamicTaskNamespace businessGrabTimeoutNamespace = DynamicTaskNamespace
                    .dynamicTaskNamespaceByBusinessCache(cache, DriverGrabBusinessTimeout.class);

            if (businessGrabTimeoutNamespace != null) {
                LOGGER.info("当前抢单流程已经结束,则需要进行删除当前司机抢单任务配置,businessId={}", businessId);
                dynamicTaskManager.removeJob(businessGrabTimeoutNamespace);
                dynamicTaskService.deleteDynamicTaskNamespace(businessGrabTimeoutNamespace);
            }
            isFinishGrab = ResponseBack.success(true);
        }
        return isFinishGrab;
    }

    /**
     * @param orderId 当前订单id
     * @throws ResponseException 业务流水号查询为空
     * @author Anson
     * @date 17-05-15
     * @name 获取当前有效的拍单视图信息
     * 若当前业务[isValidate]逻辑删除状态为false,则返回结果result数据中为null
     * 若当前没有业务对应这个订单,则返回结果result数据中为null
     * @since 1.0.6
     */
    @Override
    @Transactional
    public ResponseBack<BusinessView> getBusinessViewByOrder(String orderId) {
        LOGGER.info("获取当前拍单视图信息,orderId={}", orderId);
        if (StringUtils.isBlank(orderId)) {
            return ResponseBack.success(null);
        }
        BusinessView view = this.getServiceViewbyOrderId(orderId);
        return ResponseBack.success(view);
    }

    @Override
    @Transactional
    public ResponseBack<DistributeDriverTask> getGrabBusinessDistributeDriverTask(String businessId) {
        DistributeDriverTask distributeDriverTask = null;
        BusinessCache businessCache = this.grabBusinessCacheService.get(businessId);
        if (businessCache != null) {
            distributeDriverTask = PojoConvertVoUtils.businessCacheConvertDistributeDriverTask(businessCache);
        }
        return ResponseBack.success(distributeDriverTask);
    }

    @Override
    @Transactional
    public ResponseBack<Boolean> driverGiveUpGrabTask(String driverId, String businessId) throws ResponseException {
        if (StringUtils.isAnyEmpty(driverId, businessId)) {
            return ResponseBack.success(false);
        }
        LOGGER.info("当前司机放弃抢单driverId={},businessId={}", driverId, businessId);
        if (!this.grabBusinessWorkCacheService.assertDriverBusinessId(driverId, businessId)) {
            LOGGER.info("当前司机放弃抢单不是当前最新的业务流程driverId={},businessId={}", driverId, businessId);
            return ResponseBack.success(true);
        }
        KV<Integer, DriverRegisterBusRelative> relativeKV = this.getValidateDriverRegisterBusRelative(driverId, this
                .driverRegisterBusRelativeService);
        DriverRegisterBusRelative relative = relativeKV.getV();
        boolean isGiveUp = false;
        if (relative.assertGrabBusiness()) {
            LOGGER.info("当前司机放弃抢单并是存于抢单业务中driverId={},businessId={}", driverId, businessId);
            //放弃抢单,则当前司机必须是抢单状态才能放弃抢单
            isGiveUp = this.grabBusinessWorkCacheService.giveUpGrab(driverId);
            LOGGER.info("当前司机放弃抢单业务缓存处理是否成功,driverId={},businessId={},isGiveUp={}", driverId, businessId, isGiveUp);
            if (isGiveUp) {
                isGiveUp = grabDriverRegisterBusRelativeService.giveUpDriverBusinessGrab(relative);
                LOGGER.info("当前司机放弃抢单数据库处理是否成功,driverId={},businessId={},isGiveUp={}", driverId, businessId, isGiveUp);
            }
        } else {
            LOGGER.info("当前司机放弃抢单业务状态不是抢单中driverId={},businessId={}", driverId, businessId);
        }
        return ResponseBack.success(isGiveUp);
    }

    @Override
    @Transactional
    public ResponseBack<Boolean> handlerDriversGrabStatus(BusPoint[] busPoints, String businessId) {
        if (ArrayUtils.isEmpty(busPoints)) {
            return ResponseBack.success(false);
        }
        for (BusPoint busPoint : busPoints) {
            this.handlerDriversGrabStatus(busPoint.getDriverId(), businessId);
        }
        return ResponseBack.success(true);
    }

    @Override
    @Transactional
    public ResponseBack<Boolean> handlerDriversGrabStatus(String driverId, String businessId) {
        if (StringUtils.isBlank(driverId)) {
            return ResponseBack.success(false);
        }
        KV<Integer, DriverRegisterBusRelative> relativeKV = this.getValidateDriverRegisterBusRelative(driverId, this
                .driverRegisterBusRelativeService);
        DriverRegisterBusRelative relative = relativeKV.getV();
        if (relative.assertActive()) {
            //确认当前司机处于激活状态
        }
        boolean isGrab = this.grabBusinessWorkCacheService.doGrabBusiness(driverId, businessId);
        if (isGrab) {
            isGrab = this.grabDriverRegisterBusRelativeService.doBusinessGrab(relative);
        }
        return ResponseBack.success(isGrab);
    }

    @Override
    @Transactional
    public BusinessView[] getServiceViewByBusinessIds(String[] businessIds) {
        BusinessView[] businessViews = new BusinessView[0];
        if (StringUtils.isAnyEmpty(businessIds)) {
            return businessViews;
        }
        List<BusinessServiceInfo> infos = this.businessServiceInfoService.getInfoByBusinessIds(businessIds);
        if (CollectionUtils.isEmpty(infos)) {
            return businessViews;
        }
        int size = infos.size();
        businessViews = new BusinessView[size];
        BusinessServiceInfo info = null;
        for (int i = 0; i < size; i++) {
            info = infos.get(i);
            businessViews[i] = convertInfoToBusinessViews(info);
        }
        return businessViews;
    }

    @Override
    @Transactional
    public BusinessBaseLimitStatus accBusinessStatus(String businessId) {
        BusinessServiceInfo info = this.businessServiceInfoService.getInfoByBusinessId(businessId);
        return getInnerLimitStatus(info);
    }

    @Override
    @Transactional
    public BusinessBaseLimitStatus getInnerLimitStatus(BusinessServiceInfo info) {
        return info == null ? new BusinessBaseLimitStatus() : info.getLimitStatus();
    }

    @Override
    @Transactional
    public ResponseBack<Boolean> bespeakToBusiness(String driverId, String businessId) {
        if (StringUtils.isAnyEmpty(driverId, businessId)) {
            //非法参数
            throw new ResponseException(RPC_PARAM_ILLEGAL_ERROR);
        }
        BusinessServiceInfo businessServiceInfo = this.businessServiceInfoService.getInfoByBusinessId(businessId);
        BusinessService businessService = this.businessServiceService.getBusinessByBusinessId(businessId);
        if (businessService == null || businessServiceInfo == null) {
            //当前实体参数不存在
            throw new ResponseException(RPC_PARAM_ENTITY_ERROR);
        }
        if (!businessService.assertBespeakSuccess()) {
            //当前不处于预约抢单成功中
            return ResponseBack.success(false);
        }
        if (!driverId.equals(businessService.getDriverId())) {
            //当前司机不是业务司机本人
            throw new ResponseException(RPC_PARAM_ENTITY_ERROR);
        }
        KV<Integer, DriverRegisterBusRelative> relativeKV = this.getValidateDriverRegisterBusRelative(driverId, this
                .grabDriverRegisterBusRelativeService);
        DriverRegisterBusRelative relative = relativeKV.getV();
        Date bespeakDate = businessServiceInfo.getBespeakTime();
        String redisBespeakDate = convertor.convertCornA().convert(bespeakDate);
        //删除司机预约的日期序号
        boolean isDone = this.grabBusinessWorkCacheService.deleteBespeakDate(driverId, redisBespeakDate);
        LOGGER.info("司机某一个预约单开始向预约地行驶->driverId={},businessId={},缓存预约删除预约时间={}", driverId, businessId, isDone);
        if (!isDone) {
            return ResponseBack.success(isDone);
        }
        //修改当前司机缓存状态
        isDone = grabBusinessWorkCacheService.bespeakToBusiness(driverId, businessId);
        LOGGER.info("司机某一个预约单开始向预约地行驶->driverId={},businessId={},修改当前司机缓存状态={}", driverId, businessId, isDone);
        if (!isDone) {
            return ResponseBack.success(isDone);
        }
        isDone = this.businessServiceService.bespeakToBusiness(businessService, relative);
        LOGGER.info("司机某一个预约单开始向预约地行驶->driverId={},businessId={},处理数据服务={}", driverId, businessId, isDone);
        if (isDone) {
            isDone = false;
            try {
                relative.setAbleBeginBusiness();
                this.grabDriverRegisterBusRelativeService.update(relative);
                this.businessCacheService.updateStatus(businessId, BusinessStatus.BEGIN_BUSINESS);
                isDone = true;
            } catch (Exception e) {
                LOGGER.error("司机某一个预约单开始向预约地行驶->driverId={},businessId={},更新司机状态={}", driverId, businessId, isDone);
                throw new ResponseException(RPC_SYSTEM_CODE_ERROR);
            }
        } else {
            //加入当前数据库操作失败的时候,恢复当前缓存中司机预约的天数
            this.grabBusinessWorkCacheService.addBespeakDate(driverId, redisBespeakDate);

        }
        return ResponseBack.success(isDone);
    }

    @Override
    @Transactional
    public ResponseBack<Boolean> bespeakCancel(String userId, final String businessId, Long
            bespeakUserCancelValidateLimitSeconds) {
        if (StringUtils.isAnyEmpty(userId, businessId)) {
            return ResponseBack.success(false);
        }
        BusinessServiceInfo businessServiceInfo = this.businessServiceInfoService.getInfoByBusinessId(businessId);
        BusinessService businessService = this.businessServiceService.getBusinessByBusinessId(businessId);
        if (businessService == null || businessServiceInfo == null) {
            //当前实体参数不存在
            throw new ResponseException(RPC_PARAM_ENTITY_ERROR);
        }
        if (!userId.equals(businessService.getUserId())) {
            //当前司机不是业务用户本人
            throw new ResponseException(RPC_PARAM_ENTITY_ERROR);
        }
        if (bespeakUserCancelValidateLimitSeconds == null) {
            bespeakUserCancelValidateLimitSeconds = this.springConfigConstant.bespeakUserCancelValidateLimitSeconds();
        }
        if (!businessService.assertBespeakSuccess()) {
            //当前不处于预约抢单成功中
            LOGGER.info("用户取消预约单->userId={},businessId={},是否允许取消的时间限制={}业务状态不处于预约成功的状态", userId, businessId);
            throw new ResponseException(RPC_USER_CANCEL_BESPEAK_NOT_IN_BESPEAK_ERROR);
        }
        long limitMillSeconds = bespeakUserCancelValidateLimitSeconds * 1000;
        Date createTime = businessServiceInfo.getCreateTime();
        if (createTime == null) {
            createTime = new Date();
        }
        long createTimeMillSeconds = createTime.getTime();
        long curTime = System.currentTimeMillis();
        //剩余时间 = 业务创建时间戳(单位毫秒) + 预约有效时间(单位毫秒) - 当前时间戳(单位毫秒)
        long retainMillSeconds = createTimeMillSeconds + limitMillSeconds - curTime;
        if (retainMillSeconds > 0) {
            LOGGER.info("用户取消预约单->userId={},businessId={},是否允许取消的时间限制={}", userId, businessId, true);
            Date bespeakDate = businessServiceInfo.getBespeakTime();
            String driverId = businessService.getDriverId();
            String redisBespeakDate = convertor.convertCornA().convert(bespeakDate);
            //删除司机预约的日期序号
            boolean isDone = this.grabBusinessWorkCacheService.deleteBespeakDate(driverId, redisBespeakDate);
            LOGGER.info("用户取消预约单->userId={},businessId={},删除司机预约的日期序号={}", userId, businessId, isDone);
            if (!isDone) {
                return ResponseBack.success(isDone);
            }
            //还有剩余时间,则可以取消预约单子
            isDone = this.businessServiceService.bespeakCancel(businessService, businessServiceInfo);
            LOGGER.info("用户取消预约单->userId={},businessId={},数据库消预约单子={}", userId, businessId, isDone);
            if (isDone) {
                //删除预约出发前的短信提醒
                this.executor.execute(() -> {
                    Map<String, Object> dataMap = new HashMap<>();
                    dataMap.putIfAbsent(BusinessIdExpireRedisEventPublish.BUSINESS_ID_KEY, businessId);
                    redisEventPublish.cancel(dataMap, redisTemplate, applicationContext, BUSINESS_ID_CONVERTER);
                });
            }
            return ResponseBack.success(isDone);
        } else {
            //已经超过了有效时间,不能取消预约单子了
            return ResponseBack.success(false);
        }
    }

    @Override
    @Transactional
    public ResponseBack<Boolean> driverCancelBusiness(String driverId, String businessId) {
        if (StringUtils.isAnyEmpty(driverId, businessId)) {
            throw new ResponseException(RPC_PARAM_ILLEGAL_ERROR);
        }

        BusinessService businessService = this.businessServiceService.getBusinessByBusinessId(businessId);
        if (businessService == null) {
            throw new ResponseException(RPC_PARAM_ENTITY_ERROR);
        }
        if ((!businessService.assertBeginBusiness()) || (!driverId.equals(businessService.getDriverId()))) {
            //如果不处于行程开始的状态的时候,是不能取消行程或者当前司机与行程列表中的司机不是同一个
            return ResponseBack.success(false);
        }
        DriverStatus driverStatus = grabBusinessWorkCacheService.getStatus(driverId);
        if (!DriverRegisterBusRelative.RelativeStatus.assertBeginBusiness(driverStatus.getStatus())) {
            //当前司机不处于行程开始的状态
            return ResponseBack.success(false);
        }
        KV<Integer, DriverRegisterBusRelative> kv = this.getValidateDriverRegisterBusRelative(driverId, this
                .grabDriverRegisterBusRelativeService);
        DriverRegisterBusRelative driverRegisterBusRelative = kv.getV();
        BusinessLock lock = new BusinessRedisLock(this.extendCacheService);
        final TerminalFacade terminalFacade = this.facade("terminal", TerminalFacade.class);
        try {
            if (lock.aquireLock()) {
                //司机状态转换为激活状态
                boolean isDone = this.grabBusinessWorkCacheService.driverCancelBusiness(driverId);
                if (!isDone) {
                    return ResponseBack.success(isDone);
                }
                isDone = this.grabDriverRegisterBusRelativeService.driverCancelBusiness(driverRegisterBusRelative);
                if (!isDone) {
                    return ResponseBack.success(isDone);
                }
                //行程业务转换为取消状态
                isDone = this.businessServiceService.driverCancelBusiness(businessService);
                if (!isDone) {
                    //事务回滚
                    throw new ResponseException(RPC_DRIVER_CANCEL_ERROR);
                }
                executor.submit(new Runnable() {
                    @Override
                    public void run() {
                        //调用用户取消行程
                        terminalFacade.tripCancel(businessId);
                    }
                });
                return ResponseBack.success(true);

            }
        } catch (Exception e) {
            throw new ResponseException(RPC_DRIVER_CANCEL_ERROR);
        } finally {
            lock.unlock();
        }
        return ResponseBack.success(false);

    }

    @Override
    @Transactional
    public ResponseBack<Boolean> modifyBusinessOrderInfo(OrderSimpleInfo info) {
        String orderId = info.getOrderId();
        String businessId = info.getBusinessId();
        int orderStatus = info.getOrderStatus();
        Double orderMoney = info.getOrderMoney();
        if (StringUtils.isEmpty(orderId) && StringUtils.isEmpty(businessId)) {
            throw new ResponseException(RPC_PARAM_ILLEGAL_ERROR);
        }
        LOGGER.info("修改业务订单状态->当前businessId={},orderId={}，orderStatus={},orderMoney={}", businessId, orderId,
                orderStatus, orderMoney);
        BusinessService businessService = null;
        if (!StringUtils.isEmpty(businessId)) {
            businessService = businessServiceService.getBusinessByBusinessId(businessId);
        } else {
            businessService = businessServiceService.getBusinessByOrderId(orderId);
        }
        if (businessService == null) {
            throw new ResponseException(RPC_PARAM_ENTITY_ERROR);
        }
        boolean isDone = businessServiceService.modifyBusinessOrderStatus(businessService, orderId, orderStatus,
                orderMoney);
        return ResponseBack.success(isDone);
    }


    @Override
    @Transactional
    public ResponseBack<Boolean> doBeginBusiness(String driverId, String businessId, String userId, BusPoint
            busPoint, BusinessRequestVo businessRequestVo) {
        boolean isDone = false;
        KV<Integer, DriverRegisterBusRelative> relativeKV = this.getValidateDriverRegisterBusRelative
                (driverId, this.driverRegisterBusRelativeService);
        DriverRegisterBusRelative relative = relativeKV.getV();
        if (!(relative.isAbleDoBeginBusiness() || relative.isAbleDoBeginBusinessInGrab())) {
            //抢单模式派单可能存在抢单以及激活状态
            LOGGER.info("开始业务->校验关系异常isAbleDoBeginBusiness=false,relative={}", relative.getStatus());
            throw new ResponseException(RPC_DRIVER_NOT_IN_BEGIN_BUSINESS_ERROR);
        }
        //绑定当前业务流水号
        isDone = this.grabBusinessWorkCacheService.assertDriverBusinessId(driverId, businessId);
        if (!isDone) {
            LOGGER.info("确认当前司机业务流水号是否一致=false,driverId={}", driverId);
            return ResponseBack.success(isDone);
        }
        UserRequestTypeInfo.UserRequestType type = UserRequestTypeInfo.UserRequestType.indexOf
                (businessRequestVo.getUserRequestInfo().getType());
        SystemDistributeBusinessContext context = null;
        switch (type) {
            case NOW:
                context = new RightNowSystemDistributeBusinessContext(relative, busPoint);
                break;
            case BESPEAK:
                context = new BespeakSystemDistributeBusinessContext(relative, busPoint);
                break;
        }
        if (context != null) {
            LOGGER.info("开始执行具体的业务请求的执行器,type={}", type);
            context.setApplicationContext(this.applicationContext);
            isDone = context.handleSystemDistributeBusiness(businessRequestVo, businessId, driverId);
        } else {
            LOGGER.info("当前业务处理的系统派单执行代理类为空,type={}", type);
            isDone = false;
        }
        return ResponseBack.success(isDone);
    }


    @Override
    @Transactional
    public ResponseBack<Boolean> doBusiness(String driverId, BusinessService businessService, AddressPoint
            addressPoint) {
        if (businessService == null || addressPoint == null) {
            return ResponseBack.success(false);
        }
        if (!this.grabBusinessWorkCacheService.assertDriverBusinessId(driverId, businessService.getBusinessId())) {
            throw new ResponseException(RPC_DRIVER_BUSINESS_RELATIVE_ERROR);
        }
        ResponseBack<Boolean> responseBack = super.doBusiness(driverId, businessService, addressPoint);
        this.updateBusinessCacheStatus(businessService.getBusinessId(), BusinessStatus.BUSINESS);
        return responseBack;
    }

    @Override
    @Transactional
    public ResponseBack<BusinessServiceInfo> doFinish(BusinessFinishVo vo) {
        if (vo == null || !vo.validate()) {
            throw new ResponseException(RPC_PARAM_ILLEGAL_ERROR);
        }
        if (!this.grabBusinessWorkCacheService.assertDriverBusinessId(vo.getDriverId(), vo.getBusinessId())) {
            throw new ResponseException(RPC_DRIVER_BUSINESS_RELATIVE_ERROR);
        }
        ResponseBack<BusinessServiceInfo> responseBack = super.doFinish(vo);
        BusinessServiceInfo info = null;
        this.updateBusinessCacheStatus(vo.getBusinessId(), BusinessStatus.FINISH);
        this.grabBusinessCacheService.deleteBusiness(vo.getBusinessId());
        return responseBack;
    }

    @Override
    @Transactional
    public ResponseBack<Boolean> doUserCancel(String userId, String businessId) {
        ResponseBack<Boolean> responseBack = super.doUserCancel(userId, businessId);
        this.updateBusinessCacheStatus(businessId, BusinessStatus.CANCEL);
        this.grabBusinessCacheService.deleteBusiness(businessId);
        return responseBack;
    }

    protected void updateBusinessCacheStatus(String businessId, BusinessStatus status) {
        this.grabBusinessCacheService.updateStatus(businessId, status);
    }

    /**
     * @param driverId   当前司机id
     * @param businessId 当前业务id
     * @param type       业务类别:抢单或者派单
     * @author Anson
     * @date 17-8-10
     * @name 根据不同的业务类别处理不同的抢单或者派单结果
     * @since 1.0.6
     */
    @Transactional
    protected ResponseBack<Boolean> businessDoBeginHandle(String driverId, String businessId, BusinessTypeEnum type) {
        if (StringUtils.isEmpty(driverId) || StringUtils.isEmpty(businessId)) {
            throw new ResponseException(RPC_PARAM_ILLEGAL_ERROR);
        }
        String businessTypeMes = type.getMsg();
        BusinessCache businessCache = businessCacheService.get(businessId);
        //从缓存中获取当前业务配置缓存并且当前业务缓存集合中是否含有当前的司机缓存
        //或者当前业务已经完成的时候
        if (businessCache == null || !businessCache.validate() || !businessCache.isContain(driverId)) {
            LOGGER.info("{}->缓存获取为空或者当前业务中不含有当前司机或者业务缓存校验不通过,isNull={}",
                    businessTypeMes, businessCache == null);
            return ResponseBack.success(false);
        }
        DriverStatus driverStatus = grabBusinessWorkCacheService.getStatus(driverId);
        BusPoint busPoint = businessWorkCacheService.getNowPoint(driverId);
        if (busPoint == null) {
            //当前的司机地理位置不存在的时候
            LOGGER.error("{}->当前的司机地理位置不存在,driverId={}", businessTypeMes, driverId);
            throw new ResponseException(RPC_NOT_FOUND_DRIVER_UPLOAD_POINT_ERROR);
        }
        //不同模式进行不同的验证
        this.validateDriverStatus(driverId, driverStatus, type, businessTypeMes);
        //数据操作
        ResponseBack<Boolean> responseBack = doHandler(type, businessTypeMes, businessCache, busPoint);
        //预约短信提示
        if (responseBack.isSuccess() && responseBack.getResult()) {
            this.executor.execute(() -> {
                Map<String, Object> dataMap = new HashMap<>();
                dataMap.putIfAbsent(BusinessIdExpireRedisEventPublish.BUSINESS_CACHE_KEY, businessCache);
                redisEventPublish.publish(dataMap, redisTemplate, applicationContext, BUSINESS_ID_CONVERTER);
            });
        }
        return responseBack;
    }

    BusinessView convertInfoToBusinessViews(BusinessServiceInfo info) {
        //处理公共基础业务信息
        BusinessService businessService = info.getBusinessService();
        if (businessService == null) {
            return null;
        }
        BusinessView view = new BusinessView();
        String busId = info.getBusId();
        BusinessBaseLimitStatus status = this.getInnerLimitStatus(info);
        view.setLimitStatus(status);
        //封装车辆信息
        this.packageBusViewInfo(busId, view);
        PojoConvertVoUtils.convertBusinessInfoToView(info, view);
        return view;
    }

    @Transactional
    @Override
    public BusinessVo convertInfoToBusinessVo(BusinessServiceInfo info) {
        BusinessVo vo = PojoConvertVoUtils.serviceInfoConvertBusinessVo(info);
        if (vo == null) {
            return vo;
        }
        BusinessBaseLimitStatus status = this.getInnerLimitStatus(info);
        vo.setLimitStatus(status);
        return vo;
    }

    @Transactional
    @Override
    public ResponseBack<List<BusinessCodeServiceStatus>> getServiceByRequestType(UserRequestTypeInfo.UserRequestType
                                                                                         type) {
        if (type == null) {
            throw new ResponseException(RPC_PARAM_ILLEGAL_ERROR);
        }
        Converter<UserRequestTypeInfo.UserRequestType, List<BusinessCodeServiceStatus>> converter = new
                ServiceByRequestType(this.applicationContext);
        List<BusinessCodeServiceStatus> list = converter.convert(type);
        return ResponseBack.success(list);
    }

    @Override
    @Transactional
    public ResponseBack<Pagination<BusinessServiceInfoVo>> queryBusinessInfoByPage(PageVo vo) {
        if (StringUtils.isBlank(vo.getUserId())) {
            throw new ResponseException(RPC_PARAM_ILLEGAL_ERROR);
        }
        Pagination<BusinessServiceInfo> page = this.businessServiceInfoService.queryBusinessInfoByPage(vo);
        Pagination<BusinessServiceInfoVo> result = this.convertPageToResult(page);
        return ResponseBack.success(result);
    }

    @Override
    @Transactional
    public ResponseBack<EnableGrabBusinessStatus> queryEnableGrabBusinessStatus(String businessId) {
        if (StringUtils.isBlank(businessId)) {
            throw new ResponseException(RPC_PARAM_ILLEGAL_ERROR);
        }
        EnableGrabBusinessStatus status = new EnableGrabBusinessStatus();
        BusinessCache businessCache = grabBusinessCacheService.get(businessId);
        if (businessCache == null) {
            return ResponseBack.success(status);
        }
        //封装当前状态
        packageBusinessEnableGrabStatus(status, businessCache);
        return ResponseBack.success(status);
    }


    @Override
    @Transactional
    public ResponseBack<BusinessCacheVo> queryEnableGrabBusinessCache(String businessId) {
        if (StringUtils.isBlank(businessId)) {
            throw new ResponseException(RPC_PARAM_ILLEGAL_ERROR);
        }
        BusinessCacheVo businessCacheVo = null;
        BusinessCache businessCache = grabBusinessCacheService.get(businessId);
        if (businessCache == null) {
            return ResponseBack.success(businessCacheVo);
        }
        int codeStatus = businessCache.getStatus();
        if (!(BusinessStatus.assertGrabBusiness(codeStatus)
                || BusinessStatus.assertGrabBusinessTimeout(codeStatus)
                || BusinessStatus.assertLossBusinessTimeout(codeStatus))) {
            //若不处于抢单中,司机抢单超时中,以及用户请求超时中,是获取不到当前信息
            return ResponseBack.success(businessCacheVo);
        }
        businessCacheVo = new BusinessCacheVo();
        String codeStatusMsg = BusinessStatus.getStatusMsg(codeStatus);
        EnableGrabBusinessStatus status = new EnableGrabBusinessStatus();
        //封装当前状态
        packageBusinessEnableGrabStatus(status, businessCache);
        businessCacheVo.setRequestTask(businessCache.getRequestTask());
        businessCacheVo.setBusinessId(businessId);
        businessCacheVo.setGrabBusinessStatus(status);
        businessCacheVo.setStatus(codeStatus);
        businessCacheVo.setStatusMsg(codeStatusMsg);
        return ResponseBack.success(businessCacheVo);
    }

    /**
     * @param status        当前抢单中状态
     * @param businessCache 当前缓存
     */
    private void packageBusinessEnableGrabStatus(EnableGrabBusinessStatus status, BusinessCache businessCache) {
        boolean isInGrab = BusinessStatus.assertGrabBusiness(businessCache.getStatus());
        if (isInGrab) {
            //显示时间,延迟当前真实时间3秒
            long viewDelaySeconds = 3;
            //当前时间点,单位毫秒
            long currentTime = System.currentTimeMillis();
            //业务流水号创建时间,单位毫秒
            long createTime = businessCache.getCreateDate();
            //司机抢单超时时间,单位从秒转换为毫秒
            long driverBusinessGrabTimeout = springConfigConstant.driverBusinessGrabTimeout() * 1000;
            //用户请求超时时间,单位从秒转换为毫秒
            long userBusinessBusRequestTimeout = springConfigConstant.userBusinessBusRequestTimeout() * 1000;
            //司机剩余抢单时间控制,单位秒
            long driverRetainLimitSeconds = Long.valueOf((createTime + driverBusinessGrabTimeout - currentTime) / 1000).intValue();
            //用户请求超时时间控制,单位秒
            long userLostRetainLimitSeconds = Long.valueOf((createTime + userBusinessBusRequestTimeout - currentTime) / 1000).intValue();
            //显示超时时间在真实时间内,多添加了3秒
            driverRetainLimitSeconds += viewDelaySeconds;
            //显示超时时间在真实时间内,多添加了3秒
            userLostRetainLimitSeconds += viewDelaySeconds;
            status.setIsInGrab(isInGrab);
            status.setCreateBusinessTime(createTime);
            status.setDriverGrabRetainLimitSeconds(driverRetainLimitSeconds);
            status.setUserLostRetainLimitSeconds(userLostRetainLimitSeconds);
        }
    }

    private Pagination<BusinessServiceInfoVo> convertPageToResult(Pagination<BusinessServiceInfo> page) {
        Pagination<BusinessServiceInfoVo> result = new Pagination<BusinessServiceInfoVo>();
        List<BusinessServiceInfo> list = page.getList();
        List<BusinessServiceInfoVo> resultList = new ArrayList<>();
        if (null != list && list.size() > 0) {
            for (BusinessServiceInfo info : list) {
                BusinessServiceInfoVo resultInfo = new BusinessServiceInfoVo();
                Date bespeakTime = info.getBespeakTime();
                resultInfo.setTakeTime(null == bespeakTime ? null : bespeakTime.toString());
                resultInfo.setCreateTime(info.getCreateTime().toString());
                BusinessService businessService = info.getBusinessService();
                resultInfo.setStatus(String.valueOf(businessService.getStatus()));
                resultInfo.setId(businessService.getId());
                int businessCode = businessService.getBusinessCode();
                String type = this.getType(businessCode);
                resultInfo.setType(type);
                resultInfo.setOrderStatus(businessService.getOrderStatus());
                resultInfo.setBusinessCode(businessCode);
                resultInfo.setPlanStartAddress(info.getRequestStartAddress());
                resultInfo.setPlanEndAddress(info.getRequestEndAddress());
                resultInfo.setDriverId(businessService.getDriverId());
                resultInfo.setBusinessId(businessService.getBusinessId());
                resultList.add(resultInfo);
            }
        }
        result.setAllRow(page.getAllRow());
        result.setCurrentPage(page.getCurrentPage());
        result.setTotalPage(page.getTotalPage());
        result.setPageSize(page.getPageSize());
        result.dealPage();
        result.setHasNextPage(page.isHasNextPage());
        result.setHasPreviousPage(page.isHasPreviousPage());
        result.setList(resultList);
        return result;
    }

    /**
     * 将businessCode转换为对应的类型名称
     *
     * @param
     * @author Jack
     * @date 2017/9/1
     * @name
     * @since 1.0.7
     */
    private String getType(int businessCode) {
        for (OrderSn sn : OrderSn.values()) {
            if (sn.getCode() == businessCode) {
                return sn.getMsg();
            }
        }
        return null;
    }


    @Transactional
    private BusinessView getServiceViewbyOrderId(String orderId) {
        BusinessService businessService = this.businessServiceService.getBusinessByOrderId(orderId);
        if (businessService == null) {
            return null;
        }
        //处理公共基础业务信息
        BusinessServiceInfo info = this.businessServiceInfoService.getInfoByServiceId(businessService.getId());
        if (info == null) {
            return null;
        }
        BusinessView view = this.convertInfoToBusinessViews(info);
        return view;
    }

    /**
     * @param driverStatus
     * @param type
     * @param businessTypeMes
     * @author Anson
     * @date 17-8-10
     * @name 校验当前司机开始请求业务的状态
     * @since 1.0.6
     */
    private void validateDriverStatus(String driverId, DriverStatus driverStatus, BusinessTypeEnum type, String
            businessTypeMes) {
        switch (type) {
            case DISTRIBUTE_LEAFLETS:
                //派单
                //司机存在抢单界面,未放弃抢单
                //司机放弃了抢单,但系统还是可以派单
                if (driverStatus == null ||
                        !(DriverRegisterBusRelative.RelativeStatus.assertGrabBusiness(driverStatus.getStatus())
                                || DriverRegisterBusRelative.RelativeStatus.assertActive(driverStatus.getStatus()))) {
                    LOGGER.error("{}->当前获取司机状态不是处于(抢单||激活)状态={}", businessTypeMes, driverStatus);
                    throw new ResponseException(RPC_DRIVER_GRAB_FAIL);
                }
                break;
            case GRAB_LEAFLETS:
                //抢单
                //司机确认抢单的时候,说明没有放弃抢单,则当前司机的状态为抢单状态
                if (driverStatus == null || !DriverRegisterBusRelative.RelativeStatus.assertGrabBusiness(driverStatus
                        .getStatus())) {
                    LOGGER.error("{}->当前获取司机状态不是处于抢单状态={}", businessTypeMes, driverStatus);
                    throw new ResponseException(RPC_DRIVER_GRAB_FAIL);
                }
                if (!this.grabBusinessWorkCacheService.assertDriverBusinessId(driverId, driverStatus.getBusinessId())) {
                    LOGGER.error("{}->当前获取司机业务对应错误={},driverId={}", businessTypeMes, driverStatus, driverId);
                    throw new ResponseException(RPC_DRIVER_GRAB_FAIL);
                }
                break;
            default:
        }
    }

    /**
     * @param type
     * @param businessTypeMes
     * @param businessCache
     * @param busPoint
     * @author Anson
     * @date 17-8-10
     * @name 处理司机抢单或者派单结果
     * @since 1.0.6
     */
    private ResponseBack<Boolean> doHandler(BusinessTypeEnum type, String businessTypeMes, BusinessCache
            businessCache, BusPoint busPoint) {
        ResponseBack<Boolean> responseBack = null;
        BusinessRequestVo businessRequestVo = BusinessRequestVo.instance(businessCache.getRequestTask());
        String businessId = businessCache.getBusinessId();
        String driverId = busPoint.getDriverId();
        LOGGER.info("{}->处理司机抢单或者派单结果,type={}", businessTypeMes, type);
        switch (type) {
            case GRAB_LEAFLETS:
                //抢单
                //司机抢单,则当前司机的状态必须是抢单状态
                responseBack = this.doGrabBusiness(driverId, businessId, businessCache.getUserId(), busPoint,
                        businessRequestVo);
                break;

            case DISTRIBUTE_LEAFLETS:
                //派单
                responseBack = this.doBeginBusiness(driverId, businessId, businessCache.getUserId(), busPoint,
                        businessRequestVo);
                break;

            default:
        }
        LOGGER.info("{}->操作状态={},type={},businessId={},driverId={},responseBack={}", businessTypeMes,
                type, businessId, driverId, responseBack);
        return responseBack;
    }
}
